package org.setamv.springcloud.feign.raw;

import com.fasterxml.jackson.databind.ObjectMapper;
import feign.Feign;
import feign.Logger;
import feign.Logger.Level;
import feign.codec.StringDecoder;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import feign.jaxb.JAXBContextFactory;
import feign.jaxb.JAXBDecoder;
import feign.jaxb.JAXBEncoder;
import feign.jaxrs.JAXRSContract;
import org.apache.commons.lang.time.DateUtils;
import org.setamv.springcloud.dto.OpsResponse;
import org.setamv.springcloud.entity.User;
import org.setamv.springcloud.feign.contract.CustomizedContract;
import org.setamv.springcloud.feign.contract.CustomizedContractClient;
import org.setamv.springcloud.feign.interceptor.CustomizedFeignInterceptor;

/**
 * 使用原始的Feign执行web请求
 */
public class RawFeignStarter {


    public static void main(String[] args) throws Exception {
//        feignGet();
//        feignPost();
//        feignPostXml();

        // 自定义Http客户端发送请求
        feignRequestByCustomizedClient();

        // 通过J2EE JSR311协议的方式访问http请求
//        feignGetByJSR311();

        // 通过自定义的Contract访问http请求
//        feignGetByCustomizedContract();

        //演示Feign拦截器的使用
//        feignRequestInterceptor();

        // 查看feign请求日志。
//        feignLog();
    }

    /**
     * 通过feign发送GET请求
     */
    public static void feignGet() throws Exception {
        RawFeignClient feignClient = Feign.builder()
                  .decoder(new GsonDecoder())
                  .encoder(new GsonEncoder())
                  .target(RawFeignClient.class, "http://setamv.tech:9091");
        User user = feignClient.getUser("2014");
        ObjectMapper objectMapper = new ObjectMapper();
        System.out.println(objectMapper.writeValueAsString(user));
    }

    /**
     * 通过J2EE JSR311协议的方式访问http请求<p>
     * 注意：下面的 {@linkplain JSR311FeignClient}中的接口不能喝 {@linkplain RawFeignClient}混在一起，因为@GET注解不能和@RequestLine在同一个接口中混用
     */
    public static void feignGetByJSR311() {
        // 注意，这里的
        JSR311FeignClient feignClient = Feign.builder()
                .contract(new JAXRSContract())
                .target(JSR311FeignClient.class, "http://setamv.tech:9091");
        String greetings = feignClient.sayHelloByJSR311("setamv");
        System.out.println("greetings by jsr311: " + greetings);
    }

    /**
     * 通过自定义的Contract访问http请求
     */
    public static void feignGetByCustomizedContract() {
        CustomizedContractClient feignClient = Feign.builder()
                .contract(new CustomizedContract())
                .target(CustomizedContractClient.class, "http://setamv.tech:9091");
        String greetings = feignClient.sayHello();
        System.out.println("greetings: " + greetings);
    }

    /**
     * 通过feign发送POST请求
     * @throws Exception
     */
    public static void feignPost() throws Exception {
        RawFeignClient feignClient = Feign.builder()
                .decoder(new GsonDecoder())
                .encoder(new GsonEncoder())
                .target(RawFeignClient.class, "http://setamv.tech:9091");
        User user = new User();
        user.setId("2048");
        user.setName("setamv");
        OpsResponse response = feignClient.createUser(user);
        ObjectMapper objectMapper = new ObjectMapper();
        System.out.println("response=" + objectMapper.writeValueAsString(response));
    }

    /**
     * 通过feign发送POST请求，并且，请求和响应的数据都是xml格式的
     * @throws Exception
     */
    public static void feignPostXml() throws Exception {
        JAXBContextFactory jaxbContextFactory = new JAXBContextFactory.Builder().build();
        RawFeignClient feignClient = Feign.builder()
                .encoder(new JAXBEncoder(jaxbContextFactory))
                .decoder(new JAXBDecoder(jaxbContextFactory))
                .target(RawFeignClient.class, "http://localhost:9091");
        User oriUser = new User();
        oriUser.setId("2049");
        oriUser.setName("setamv");
        oriUser.setBirthDate(DateUtils.parseDate("1985-11-13", new String[]{"yyyy-MM-dd"}));
        User user = feignClient.echoByXml(oriUser);
        ObjectMapper objectMapper = new ObjectMapper();
        System.out.println("echo user:" + objectMapper.writeValueAsString(user));
    }

    /**
     * 使用扩展自feign的Client的自定义Http客户端来发送请求
     * @throws Exception
     */
    public static void feignRequestByCustomizedClient() throws Exception {
        RawFeignClient feignClient = Feign.builder()
                .decoder(new StringDecoder())
                .client(new CustomizedHttpClient())
                .target(RawFeignClient.class, "http://setamv.tech:9091");
        // 连续访问10次，查看负载均衡是否生效
        for (int i = 0; i < 10; i++) {
            String greetings = feignClient.sayHello("setamv");
            System.out.println("customized client request user:" + greetings);
        }
    }

    /**
     * 演示Feign拦截器的使用。<p>
     * 拦截器的实现，参考 {@linkplain CustomizedFeignInterceptor}
     */
    public static void feignRequestInterceptor() {
        // 下面注册自定义的拦截器
        // 从下面的打印信息可以看到：拦截器会在进入Client执行请求之前触发
        RawFeignClient feignClient = Feign.builder()
                      .requestInterceptor(new CustomizedFeignInterceptor())
                      .decoder(new StringDecoder())
                      .client(new CustomizedHttpClient())
                      .target(RawFeignClient.class, "http://setamv.tech:9091");

        String greetings = feignClient.sayHello("setamv");
        System.out.println("customized client request user:" + greetings);
    }

    /**
     * 查看feign请求日志。feign的请求日志分为好几个级别，不同的级别可以记录不同详细程度的http请求日志
     * @throws Exception
     */
    public static void feignLog() {
        // 下面记录全部的请求日志，并将日志写入文件 ./logs/feing-request.log中
        RawFeignClient feignClient = Feign.builder()
                      .logLevel(Level.FULL)
                      .logger(new Logger.JavaLogger().appendToFile("./logs/feing-request.log"))
                      .target(RawFeignClient.class, "http://setamv.tech:9091");
        String greetings = feignClient.sayHello("setamv");
        System.out.println("greetings: " + greetings);
    }

}
